/****************************************************************************
*					GreedyAlgorithm
*
*	Description:	Improved greedy algorithm for structure learning of PGM
*
****************************************************************************/

#ifndef _GreedyAlgorithm_H
#define _GreedyAlgorithm_H

#include <vector>
#include <math.h>
#include "PGMStruct.h"
#include "DataSet.h"
#include "StructureLearning.h"
#include "ParameterLearning.h"
#include "ParameterLearningFactory.h"
#include "Inference.h"
#include "InferenceFactory.h"

class GreedyAlgorithm : public StructureLearning {
  private:

  protected:

	  

	  // Algorithm for optimizing parameters of the PGM
	ParameterLearning* parameterLearning;

	  // Algorithm for running inference
	Inference* inference;

	  /* FUNCTIONS */
	  // Function to calculate gain in likelihood given EP value and EQ value for a feature
	static inline double likelihoodGain (const double& empiricalProb, const double& mrfProb) {
		return pow((empiricalProb / mrfProb), empiricalProb) * pow ((1 - empiricalProb) / (1 - mrfProb), 1 - empiricalProb); }
	static inline float likelihoodGain (const float& empiricalProb, const float& mrfProb) {
		return pow((empiricalProb / mrfProb), empiricalProb) * pow ((1 - empiricalProb) / (1 - mrfProb), 1 - empiricalProb); }

	// Function sets new feature weight given its emprical probability and expected value w.r.t. current state of PGM
	static inline double weightValue (const double& empiricalProb, const double& mrfProb) {
		return (double) log ((empiricalProb / (1 - empiricalProb)) * ((1 - mrfProb)  / mrfProb)); }
	static inline float weightValue (const float& empiricalProb, const float& mrfProb) {
		return (float) log ((empiricalProb / (1 - empiricalProb)) * ((1 - mrfProb)  / mrfProb)); }

	  // Return a vector of all possible features (with limitation set by maxSizeOfArbitraryFeats)
	int getAllPossibleFeatures (std::vector < std::vector < std::pair <unsigned int, unsigned int> > >& allFeats, PGMStruct& pgmStruct);

  public:
// TEMPORARY PURPOSES ONLY _ TESTING
	  /* DATA */
	  // max size of arbitrary features (for them to be used in the algorithm)
	unsigned int maxSizeOfArbitraryFeats;
	  // max number of all featues in the PGM
	unsigned int maxWholeNumOfFeats;
	  // stopping criteria: if the we get same objective function value for thin number of iterations - than stop
	unsigned int numIterWithSameValue;
	  // min acceptable gain in likelihood to continue adding features with high EP
	double minLikelihoodGain;
// END OF TESTING

	  // Standard constructor
	GreedyAlgorithm(void);
      
	  // Standard destructor
    ~GreedyAlgorithm();

      // Calculating feature value
	int learn (DataSet& dataSetLearn, PGMStruct& pgmStruct);

	  // Set object patameters from environment
	int setParameters (Environment &environment);

}; // end of class

#endif // _GreedyAlgorithm_H
